import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.aspectj.lang.Signature;

public aspect TraceAspect extends IndentedLogging {

	private org.apache.log4j.Logger _logger = Logger.getLogger("trace");

	public TraceAspect() {

		super();
		BasicConfigurator.configure();
		_logger.setLevel(Level.ALL);
	}

	pointcut traceMethods()
        : (execution(* *.*(..))
          || execution(*.new(..))) && !within(TraceAspect);

	before() : traceMethods() {

		if (_logger.isEnabledFor(Level.INFO)) {
			Signature sig = thisJoinPointStaticPart.getSignature();
			_logger.log(Level.INFO, "Entering ["
					+ sig.getDeclaringType().getName() + "." + sig.getName()
					+ "]");
		}
	}

	pointcut exceptionLogMethods() 
    : call(* *.*(..)) && 
      !within(TraceAspect);

	after() throwing(Throwable ex) : exceptionLogMethods() {

		if (_logger.isEnabledFor(Level.ERROR)) {

			Signature sig = thisJoinPointStaticPart.getSignature();
			_logger.log(Level.ERROR, "Exception logger aspect ["
					+ sig.getDeclaringType().getName() + "." + sig.getName()
					+ "]", ex);
		}
	}

	protected pointcut loggedOperations() 
    : (execution(* *.*(..)) 
       || execution(*.new(..))) && !within(TraceAspect) && !within(IndentedLogging+);

	before() : loggedOperations() {
		Signature sig = thisJoinPointStaticPart.getSignature();
		System.out.println("Entering [" + sig.getDeclaringType().getName()
				+ "." + sig.getName() + "]");
	}

}
